package call

import (
	"dmsv/fclient"
	"github.com/beego/beego/v2/core/logs"
	"github.com/g2fly99/esl"
	"sync"
	"time"
)

var gCalls sync.Map
var gChannel chan *fclient.EventInfo
var gSessionChannel chan *CallEvent

const (
	CALL_DIR_OUT    = "out"
	CALL_DIR_IN     = "in"
	LEG_DIR_USER    = "user"
	LEG_DIR_SERVICE = "service"
	LEG_DIR_OUTCALL = "outcall"
)

func createNewCallFromPstn(msg *fclient.EventInfo) {

	ev, ok := msg.Data.(*esl.Event)
	if !ok {
		logs.Error("消息类型数据格式不正确:%v", msg)
		return
	}

	caller := ev.Get("Caller-Caller-ID-Number")
	callTo := ev.Get("Caller-Destination-Number")

	newCall := &CallInfo{
		callDir:    CALL_DIR_IN,
		fCallId:    ev.UId,
		Caller:     caller,
		Callee:     callTo,
		ispstn:     true,
		CreateTime: time.Now(),
		StartTime:  msg.EvTime,
		legDir:     LEG_DIR_USER,
	}

	//呼入通知,新建call信息
	if ev.ProfileIsInternal() {
		// 坐席呼入，说明是直拨
		newCall.legDir = LEG_DIR_SERVICE
		newCall.ispstn = false
		logs.Debug("%v new direct call;caller:%v,callto:%v", newCall.fCallId, caller, callTo)
	} else {
		logs.Debug("%v new coming call;用户号码 :%v,中继号: %v", newCall.fCallId, caller, callTo)
	}

	//启动call事件协程
	go newCall.evRunRoutine()
	gCalls.Store(newCall.fCallId, newCall)

	//发送到session模块
	evt := &CallEvent{
		Name:   C_EVENT_CREATE,
		Call:   newCall,
		EvTime: msg.EvTime,
	}
	gSessionChannel <- evt
}

func createCall(callId, caller, callee, legDir string) *CallInfo {

	newCall := &CallInfo{
		fCallId:    callId,
		Caller:     caller,
		Callee:     callee,
		legDir:     legDir,
		ispstn:     true,
		CreateTime: time.Now(),
	}

	return newCall
}

func Init(fsHost, psswd string, ssChannel chan *CallEvent) error {

	//启动老化检查
	go callClean()

	gChannel = make(chan *fclient.EventInfo, 1000)
	go eventRoutine()

	gSessionChannel = ssChannel

	return fclient.NewFsConn(fsHost, psswd, gChannel)
}

func rangeCalls(key interface{}, value interface{}) bool {

	c, ok := value.(*CallInfo)
	if !ok {
		logs.Error("[%v] 数据类型不正确:%v", key, value)
	} else {
		if time.Since(c.CreateTime) > 4*time.Hour {
			logs.Error("[%v] 超时未结束,销毁。", key)
			c.destroy()
		}
	}

	return true
}

func callClean() {

	for {
		gCalls.Range(rangeCalls)
		time.Sleep(1 * time.Hour)
	}
}

func eventRoutine() {

	for {

		event := <-gChannel
		//logs.Debug("[%v] 新的事件: %v ", event.CallId, event.Name)
		val, ok := gCalls.Load(event.CallId)
		if !ok && fclient.CALL_EVENT_CREATE == event.Name {
			//用户呼入
			createNewCallFromPstn(event)
			continue
		} else if !ok {
			logs.Debug("[%v] 会话未存储 [%v],事件延迟:%v ", event.CallId, event.Name, time.Since(event.EvTime))
			if time.Since(event.EvTime) < 1*time.Second {
				time.AfterFunc(200*time.Millisecond, func() { gChannel <- event })
			} else {
				logs.Debug("[%v] [%v],事件超时:%v ,丢弃", event.CallId, event.Name, time.Since(event.EvTime))
			}

			continue
		}

		call, ok := val.(*CallInfo)
		if ok {
			//发往call的事件队列
			if call.msgChan != nil {
				call.msgChan <- event
			} else {
				logs.Error("[%v] 消息通道已关闭, 丢弃消息", call.sessionId)
			}

		} else {
			logs.Error("错误的数据类型:%v,", val)
		}
	}
}
